package com.terra.ns.imp.system.service.impl

import cn.hutool.crypto.SmUtil
import cn.hutool.extra.spring.SpringUtil
import com.terra.micro.portal.common.service.vo.organization.user.request.EditPasswordRequest
import com.terra.ns.imp.common.satoken.utils.LoginUtils
import com.terra.ns.imp.common.vo.request.ByCodeRequest
import com.terra.ns.imp.common.vo.request.PageParam
import com.terra.ns.imp.common.vo.request.QueryByKeywordsRequest
import com.terra.ns.imp.common.vo.response.PageResult
import com.terra.ns.imp.system.api.entity.StUser
import com.terra.ns.imp.system.api.enums.UserStatusEnum
import com.terra.ns.imp.system.config.SystemCustomProperties
import com.terra.ns.imp.system.constant.SystemErrorCode
import com.terra.ns.imp.system.constant.enums.UserDepRelMainDeptEnum
import com.terra.ns.imp.system.constant.enums.UserEventEnum
import com.terra.ns.imp.system.convert.*
import com.terra.ns.imp.system.event.UserEvent
import com.terra.ns.imp.system.exception.SystemServiceException
import com.terra.ns.imp.system.mapper.*
import com.terra.ns.imp.system.service.IStUserService
import com.terra.ns.imp.system.vo.base.UserBaseRequest
import com.terra.ns.imp.system.vo.base.UserBaseResponse
import com.terra.ns.imp.system.vo.request.*
import com.terra.ns.imp.system.vo.response.OrgItemResponse
import com.terra.ns.imp.system.vo.response.UserDetailResponse
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

/**
@author qins
@date 2023/6/14
@desc
 */
@Service
class StUserServiceImpl: IStUserService {


    @Autowired
    private lateinit var systemCustomProperties: SystemCustomProperties

    @Autowired
    private lateinit var userMapper: StUserMapper

    @Autowired
    private lateinit var userDeptRelMapper: StUserDeptRelMapper

    @Autowired
    private lateinit var userRoleRelMapper: StUserRoleRelMapper

    @Autowired
    private lateinit var departmentMapper: StDepartmentMapper

    @Autowired
    private lateinit var roleMapper: StRoleMapper

    override fun selectUserPage(request: PageParam<QueryByKeywordsRequest>): PageResult<UserDetailResponse> {
//        val keywords = request.param?.keywords
//        val pageResult = userCompanyRelMapper.selectPageByTenantIdAndKeywords(request, tenantId, keywords)
//        if(pageResult.isEmpty()) return PageResult()
//        val dataList = pageResult.result!!
//        val userCodes = dataList.mapNotNull { it.userCode }
//        val userDepts = userDeptRelMapper.selectListByUserCodes(userCodes, tenantId)
//        val userRoles = userRoleRelMapper.selectListByUserCodes(userCodes, tenantId)
//        val depts = departmentMapper.selectListByCodes(userDepts.mapNotNull { it.departmentCode }, tenantId)
//        val roles = roleMapper.selectListByCodes(userRoles.mapNotNull { it.roleCode }, tenantId)
//        val responseData = UserConvert.convertUserCompanyDetailResponse(dataList, userDepts, userRoles, depts, roles)
//        return pageResult.convert(responseData)
        return PageResult()
    }

    @Transactional
    override fun addUser(request: AddUserRequest) {
        // 系统是否已有用户
//        val user = userMapper.selectOneByPhone(request.phone)
//        if(user == null) {
//            val newUser = UserConvert.convert(request.phone, encodePassword(null))
//            userMapper.insert(newUser)
//        } else {
//            val userCode = user.code!!
//            requireStatusNormal(user)
//            val userCompanyRel = userCompanyRelMapper.selectOneByUserCodeAndTenantId(userCode, tenantId)
//            if(userCompanyRel != null) throw SystemServiceException(SystemErrorCode.USER_EXIST_IN_COMPANY)
//            addUserCompanyRel(userCode, tenantId, request)
//        }
    }

    @Transactional
    override fun updateUser(request: EditUserRequest) {
//        val userCompanyRel = userMapper.selectOneByCode(request.code)
//            ?: throw SystemServiceException(SystemErrorCode.USER_EXIST_IN_COMPANY)
//        val updateUserCompanyRel = UserConvert.convertUpdate(request)
//        // 更新部门关系
//        val existRelList = userDeptRelMapper.selectListByUserCode(request.code, tenantId)
//        if(existRelList.isNotEmpty()) {
//            userDeptRelMapper.deleteBatchIds(existRelList.mapNotNull { it.id})
//        }
//        addUserDeptRel(request.code, tenantId, request)
    }

    @Transactional
    override fun deleteUser(request: ByCodeRequest) {
        userDeptRelMapper.deleteByUserCode(request.code)
        userRoleRelMapper.deleteByUserCode(request.code)
        SpringUtil.publishEvent(UserEvent(listOf(request.code), UserEventEnum.DELETE))
    }

    @Transactional
    override fun assignRole(request: UserAssignRoleRequest) {
        val existRelList = userRoleRelMapper.selectListByUserCode(request.code)
        if(existRelList.isNotEmpty()) {
            userRoleRelMapper.deleteBatchIds(existRelList.mapNotNull { it.id})
        }
        val userRoleRelList = request.roleCodeList.map {
            UserRoleRelConvert.convert(request.code, it)
        }
        userRoleRelMapper.batchInsertByBatchSize(userRoleRelList)
    }

    override fun modifyPwd(request: EditPasswordRequest) {
        val userCode = LoginUtils.getUserCode()
        val user = userMapper.selectOneByCode(userCode)
            ?: throw SystemServiceException(SystemErrorCode.USER_NOT_EXIST_AT_PLATFORM)
        if(request.oldPassword != user.password) {
            throw SystemServiceException(SystemErrorCode.USER_OLD_PASSWORD_ERROR)
        }
        val update = StUser()
        update.password = request.password
        update.id = user.id
        userMapper.updateById(update)
    }

    override fun resetPassword(request: ByCodeRequest) {
        val user = userMapper.selectOneByCode(request.code)
            ?: throw SystemServiceException(SystemErrorCode.USER_NOT_EXIST_AT_PLATFORM)
        val update = StUser()
        update.password = encodePassword(null)
        update.id = user.id
        userMapper.updateById(update)
    }

    override fun forgetLoginPassword(request: ForgetPasswordRequest) {
        TODO("Not yet implemented")
    }


    override fun getDetailUser(request: ByCodeRequest): UserDetailResponse {
//        val userCompany = userMapper.selectOneByCode(request.code)
//            ?: throw SystemServiceException(SystemErrorCode.USER_EXIST_IN_COMPANY)
//        val userDeptList = userDeptRelMapper.selectListByUserCode(request.code)
//        val userRoleList = userRoleRelMapper.selectListByUserCode(request.code)
//        val deptMap = departmentMapper.selectListByCodes(userDeptList.mapNotNull { it.departmentCode })
//            .associateBy { it.code }
//        val roleMap = roleMapper.selectListByCodes(userRoleList.mapNotNull { it.roleCode })
//            .associateBy { it.code }
//        val mainDeptCode = userDeptList.first { it.mainDept == UserDepRelMainDeptEnum.IS_MAIN_DEPT.code }.departmentCode
//        val userMainDeptResponse = DepartmentConvert.convertToBaseResponse(deptMap[mainDeptCode]!!)
//        val userDeptResponse = userDeptList.filterNot { deptMap[it.departmentCode] == null }.map { DepartmentConvert.convertToBaseResponse(deptMap[it.departmentCode]!!) }
//        val userRoleResponse = userRoleList.filterNot { roleMap[it.roleCode] == null }.map { RoleConvert.convertToBaseResponse(roleMap[it.roleCode]!!) }
//        return UserConvert.convertUserCompanyDetailResponse(userCompany, userDeptResponse, userRoleResponse, userMainDeptResponse)
        return UserDetailResponse()
    }

    override fun getUserList(request: QueryByKeywordsRequest): List<UserBaseResponse> {
        val userCompanyList = userMapper.selectListByKeywords(request.keywords)
        return userCompanyList.map { UserConvert.convertUserBaseResponse(it) }
    }

    override fun queryOrgList(request: QueryOrgRequest): List<OrgItemResponse> {
        val keywords = request.keywords
        val checkType = request.type
        val key = request.key // 取部门下级数据的部门编码
        val response = ArrayList<OrgItemResponse>()
//        if(!keywords.isNullOrBlank()) {  // 是通过搜索的，则直接返回搜索相关数据，不支持翻级
//            if(checkType.isNullOrEmpty() || checkType.contains(OrgCheckTypeEnum.ROLE.type)) {
//                val roleList = roleMapper.selectLikeName(keywords, tenantId)
//                response.addAll(roleList.map { UserConvert.convertOrgItemResponse(it) })
//            }
//            if(checkType.isNullOrEmpty() || checkType.contains(OrgCheckTypeEnum.USER.type)) {
//                val userList = userCompanyRelMapper.selectByLikeName(keywords, tenantId)
//                response.addAll(userList.map { UserConvert.convertOrgItemResponse(it) })
//            }
//            if(checkType.isNullOrEmpty() || checkType.contains(OrgCheckTypeEnum.DEPT.type)) {
//                val deptList = departmentMapper.selectByLikeName(keywords, tenantId)
//                response.addAll(deptList.map { UserConvert.convertOrgItemResponse(it) })
//            }
//        } else {
//            if(key.isNullOrBlank()) { // 返回顶级数据
//                if(checkType.isNullOrEmpty() || checkType.contains(OrgCheckTypeEnum.ROLE.type)) {
//                    val roleList = roleMapper.selectLikeName(keywords, tenantId)
//                    response.addAll(roleList.map { UserConvert.convertOrgItemResponse(it) })
//                }
//                if(checkType.isNullOrEmpty() || checkType.contains(OrgCheckTypeEnum.DEPT.type) || checkType.contains(OrgCheckTypeEnum.USER.type)) {
//                    val deptList = departmentMapper.selectByParentCode(SystemConstants.TOP_DEPT_PARENT_CODE, tenantId)
//                    response.addAll(deptList.map { UserConvert.convertOrgItemResponse(it, true) })
//                }
//            } else { // 只返回对应部门级数据
//                val deptList = departmentMapper.selectByParentCode(key, tenantId)
//                response.addAll(deptList.map { UserConvert.convertOrgItemResponse(it, true) })
//                if(checkType.isNullOrEmpty() || checkType.contains(OrgCheckTypeEnum.USER.type)) {
//                    val userCodes = userDeptRelMapper.selectListByDeptCode(key, tenantId).mapNotNull { it.userCode }
//                    val userList = userCompanyRelMapper.selectListByUserCodes(userCodes, tenantId)
//                    response.addAll(userList.map { UserConvert.convertOrgItemResponse(it) })
//                }
//            }
//
//        }
        return response
    }

    override fun getUserByDept(request: ByCodeRequest): List<UserBaseResponse> {
        val userCodes = userDeptRelMapper.selectListByDeptCode(request.code).mapNotNull { it.userCode }
        val userList = userMapper.selectListByCodes(userCodes)
        return userList.map { UserConvert.convertUserBaseResponse(it) }
    }

    override fun getUserByRole(request: ByCodeRequest): List<UserBaseResponse> {
        val userCodes = userRoleRelMapper.selectListByRoleCodeAndTenantId(request.code).mapNotNull { it.userCode }
        val userList = userMapper.selectListByCodes(userCodes)
        return userList.map { UserConvert.convertUserBaseResponse(it) }
    }

    override fun requireStatusNormal(user: StUser) {
        if(UserStatusEnum.NORMAL.code != user.status) {
            throw SystemServiceException(SystemErrorCode.USER_STATUS_EXCEPTION_AT_PLATFORM)
        }
    }

    override fun encodePassword(password: String?): String {
        return if(password.isNullOrBlank()) {
            SmUtil.sm3(systemCustomProperties.initLoginPassword)
        } else {
            SmUtil.sm3(password)
        }
    }

    fun addUserDeptRel(userCode: String, request: UserBaseRequest) {
        if(request.mainDeptCode.isNullOrBlank()) request.mainDeptCode = request.deptCodeList[0]
        val newDeptRelList = request.deptCodeList.map {
            UserDeptRelConvert.convert(userCode, it, request.mainDeptCode)
        }
        userDeptRelMapper.batchInsertByBatchSize(newDeptRelList)
    }
}